#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include "vector.h"

#define PI 3.14159265

/*------------------------------------------------------------------
Constructor - Default.
Sets 0 to x, y and z
/-------------------------------------------------------------------*/
Vector::Vector()
{
#if DEBUG
	//
#endif

	x=y=z=0;
}

/*------------------------------------------------------------------
Constructor - 3 doubles
Takes 3 double values as input to set the x, y and z values
/-------------------------------------------------------------------*/
Vector::Vector(double xx,double yy,double zz)
{
#if DEBUG
	//
#endif

	setVector(xx,yy,zz);
}

/*------------------------------------------------------------------
Constructor - double array
Take an array of size 3 to set the x, y and z values
/-------------------------------------------------------------------*/
Vector::Vector(double v[])
{
#if DEBUG
	//
#endif

	setVector(v);
}

/*------------------------------------------------------------------
Destructor
No dynamic memory allocated, so empty.
/-------------------------------------------------------------------*/
Vector::~Vector()
{
#if DEBUG
	//
#endif

	//
}

/*------------------------------------------------------------------
setVector - 3 doubles
Takes double inputs to set x, y and z values
/-------------------------------------------------------------------*/
void Vector::setVector(double xx,double yy,double zz)
{
#if DEBUG
	//
#endif

	x=xx;
	y=yy;
	z=zz;
}

/*------------------------------------------------------------------
setVector - array
Takes a double array of size 3 to set x, y and z values
/-------------------------------------------------------------------*/
void Vector::setVector(double v[])
{
#if DEBUG
	//
#endif

	x=v[0];
	y=v[1];
	z=v[2];
}

/*------------------------------------------------------------------
setRandom
Takes a min and max value and generates a random vector within the range.
Generates a result with 2 decimal places.
/-------------------------------------------------------------------*/
void Vector::setRandom(int min,int max)
{
#if DEBUG
	//
#endif

	double x,y,z;
	srand(time(NULL));

	//Multiplying by 100 allows us to divide the result by 100 to produce 2 decimal places
	min*=100;
	max*=100;

	x=rand() % (max-min) + min;
	y=rand() % (max-min) + min;
	z=rand() % (max-min) + min;

	//Creates 2 decimal places
	setVector(x/100,y/100,z/100);
}

/*------------------------------------------------------------------
setX
Sets the x value with a double
/-------------------------------------------------------------------*/
void Vector::setX(double xx)
{
#if DEBUG
	//
#endif

	x=xx;
}

/*------------------------------------------------------------------
setY
Sets the y value with a double
/-------------------------------------------------------------------*/
void Vector::setY(double yy)
{
#if DEBUG
	//
#endif

	y=yy;
}

/*------------------------------------------------------------------
setZ
Sets the z value with a double
/-------------------------------------------------------------------*/
void Vector::setZ(double zz)
{
#if DEBUG
	//
#endif

	z=zz;
}

/*------------------------------------------------------------------
getMag
Gets te magnitude of the vector
/-------------------------------------------------------------------*/
double Vector::getMag()
{
#if DEBUG
	//
#endif

	return sqrt(getMagSq());
}

/*------------------------------------------------------------------
getMagSq
Gets the squared magnitude of the vector
/-------------------------------------------------------------------*/
double Vector::getMagSq()
{
#if DEBUG
	//
#endif

	return pow(x,2)+pow(y,2)+pow(z,2);
}

/*------------------------------------------------------------------
getDir
Gets the direction of a vector
/-------------------------------------------------------------------*/
double Vector::getDir(Vector v)
{
#if DEBUG
	//
#endif

	return acos(getDot(v)/(getMag()*v.getMag()))*180/PI;
}

/*------------------------------------------------------------------
getSum
Adds two vectors together
/-------------------------------------------------------------------*/
Vector Vector::getSum(Vector v)
{
#if DEBUG
	//
#endif

	Vector sum;

	sum.setVector(getX()+v.getX(),getY()+v.getY(),getZ()+v.getZ());

	return sum;
}

/*------------------------------------------------------------------
getDiff
Takes the difference of two vectors
/-------------------------------------------------------------------*/
Vector Vector::getDiff(Vector v)
{
#if DEBUG
	//
#endif

	Vector diff;

	diff.setVector(getX()-v.getX(),getY()-v.getY(),getZ()-v.getZ());

	return diff;
}

/*------------------------------------------------------------------
getDot
Finds the dot product of two vectors.
/-------------------------------------------------------------------*/
double Vector::getDot(Vector v)
{
#if DEBUG
	//
#endif

	return getX()*v.getX()+getY()*v.getY()+getZ()*v.getZ();
}

/*------------------------------------------------------------------
getCross
Finds the cross product of two vectors
/-------------------------------------------------------------------*/
Vector Vector::getCross(Vector v)
{
#if DEBUG
	//
#endif

	Vector cross;

	cross.setVector(getY()*v.getZ()-getZ()*v.getY(),getZ()*v.getX()-getX()*v.getZ(),getX()*v.getY()-getY()*v.getX());

	return cross;
}

/*------------------------------------------------------------------
getEqual
Determines whether two vectors are equal.
/-------------------------------------------------------------------*/
bool Vector::getEqual(Vector v)
{
#if DEBUG
	//
#endif

	bool eq=false;

	if(getX()==v.getX() && getY()==v.getY() && getZ()==v.getZ())
		eq = true;

	return eq;
}

/*------------------------------------------------------------------
getZero
Determines if a vector is 0.
/-------------------------------------------------------------------*/
bool Vector::getZero()
{
#if DEBUG
	//
#endif

	bool zero=false;

	if(getX()==0 && getY()==0 && getZ()==0)
		zero = true;

	return zero;
}

/*------------------------------------------------------------------
getDist
Treats two vectors as points and finds the distance between them.
/-------------------------------------------------------------------*/
double Vector::getDist(Vector v)
{
#if DEBUG
	//
#endif

	double d;

	d = sqrt(getDistSq(v));

	return d;
}

/*------------------------------------------------------------------
getDistSquared
Treats two vectors as points and finds the squared distance between them.
/-------------------------------------------------------------------*/
double Vector::getDistSq(Vector v)
{
#if DEBUG
	//
#endif

	double d;

	d = pow(v.getX()-x,2)+pow(v.getY()-y,2)+pow(v.getZ()-z,2);

	return d;
}

/*------------------------------------------------------------------
getUnitVector
Generates the unit vector of a vector.
/-------------------------------------------------------------------*/
Vector Vector::getUnitVector()
{
#if DEBUG
	//
#endif

	Vector u;
	double n[3];
	
	n[0]=x/getMag();
	n[1]=y/getMag();
	n[2]=z/getMag();

	u.setVector(n);

	return u;
}

/*------------------------------------------------------------------
getInterpolation
Interpolates, on a scale of 0 to 1, the vector between two vectors.
/-------------------------------------------------------------------*/
Vector Vector::getInterpolation(double p,Vector v)
{
#if DEBUG
	//
#endif

	Vector i;
	double n[3];

	i=getDiff(v);

	i.setX(i.getX()*p*-1);
	i.setY(i.getY()*p*-1);
	i.setZ(i.getZ()*p*-1);

	i=getSum(i);

	return i;
}